home *** CD-ROM | disk | FTP | other *** search
- #include <dos.h>
- #include <stdio.h>
- #include <string.h>
- #include <malloc.h>
- #include "modplay.h"
- #include "device.h"
-
- void fillbuffer(uchar *);
- void worknote(note *, channel *);
-
- module song;
- char * sampledata[31];
- note * patterndata[64];
- char buffer[2][2500];
-
- uint playrate;
- uint tablepos;
- uint patternpos;
- ulong patternticks;
- ulong patternticksaim;
- ulong sampleticksconst;
- channel channels[4];
-
- int
- modload(char * filename)
- {
- uint i, j, max;
- uchar a, b, c;
- sample *sptr;
- FILE *fp;
-
- if ((fp = fopen(filename, "rb")) == NULL) return 0;
- if (fread(&(song.title), 1, 1084, fp) != 1084) return 0;
- if (memcmp(&(song.signature), "M.K.", 4) != 0 &&
- memcmp(&(song.signature), "FLT4", 4) != 0 &&
- memcmp(&(song.signature), "FLT8", 4) != 0) {
- memcpy(&(song.signature), "M.K.", 4);
- memcpy(&(song.length), &(song.samples[15]), 130);
- memset(&(song.samples[15]), 0, 480);
- if (fseek(fp, 600L, SEEK_SET) != 0) return 0;
- }
- for (i = max = 0; i < 128; i++)
- while (max <= song.patterntable[i]) {
- if ((patterndata[max]=malloc(1024))==NULL) return 0;
- if (fread(patterndata[max++],1024,1,fp)!=1) return 0;
- }
- for (i = 0, sptr = song.samples; i < 31; i++, sptr++) {
- _AX = sptr->length; asm {xchg ah, al}; sptr->length = _AX * 2;
- _AX = sptr->reppnt; asm {xchg ah, al}; sptr->reppnt = _AX * 2;
- _AX = sptr->replen; asm {xchg ah, al}; sptr->replen = _AX * 2;
- if (sptr->length == 0) continue;
- if ((sampledata[i] = malloc(sptr->length)) == NULL) return 0;
- fread(sampledata[i], sptr->length, 1, fp);
- if (sptr->replen + sptr->reppnt > sptr->length)
- sptr->replen = sptr->length - sptr->reppnt;
- for (max = 0; max < sptr->length; max++)
- sampledata[i][max] ^= 0x80;
- }
- return 1;
- }
-
- int
- modinit(int frequency)
- {
- if ((sbinit(0x220, 7, 1) == 0)) return 0;
- if ((playrate = sbrate(frequency)) == 0) return 0;
- return playrate;
- }
-
- int
- modplay(void)
- {
- tablepos = 0;
- patternpos = 0;
- patternticks = 6L * playrate / 51 + 1;
- patternticksaim = 6L * playrate / 51;
- sampleticksconst = 3445744UL / playrate;
- channels[0].volume = 0; channels[0].period = 448;
- channels[1].volume = 0; channels[1].period = 448;
- channels[2].volume = 0; channels[2].period = 448;
- channels[3].volume = 0; channels[3].period = 448;
- fillbuffer(buffer[0]);
- fillbuffer(buffer[1]);
- sbdblbuf(buffer[0], 2500, buffer[1], 2500);
- return 1;
- }
-
- int
- modpoll(void)
- {
- if (tablepos > song.length) {
- return 1;
- } else if (bufoverlap) {
- return 2;
- } else if (bufempty[bufplaying^1]) {
- bufempty[bufplaying^1] = 0;
- fillbuffer(buffer[bufplaying^1]);
- return 0;
- } else
- return 0;
- }
-
- int
- modstop(void)
- {
- sbstop();
- return 0;
- }
-
- void
- fillbuffer(uchar * buffer)
- {
- uint i, j, k, l;
- note *nptr;
- channel *cptr;
-
- for (i = 0; i < 2500; i++) {
- if (patternticks++ > patternticksaim) {
- nptr = patterndata[song.patterntable[tablepos]];
- nptr = nptr + patternpos;
- cptr = channels;
- patternpos += 4;
- patternticks = 0;
- worknote(nptr+0, cptr+0);
- worknote(nptr+1, cptr+1);
- worknote(nptr+2, cptr+2);
- worknote(nptr+3, cptr+3);
- if (patternpos == 256) {
- tablepos++;
- patternpos = 0;
- }
- }
- for (j = l = 0, cptr = channels; j < 4; j++, cptr++) {
- k = sampleticksconst * cptr->ticks++ / cptr->period;
- if (k > cptr->length) {
- cptr->sampdata += cptr->reppnt;
- cptr->length = cptr->replen;
- cptr->reppnt = 0;
- cptr->ticks = 0;
- l += cptr->sampdata[0] * cptr->volume;
- } else
- l += cptr->sampdata[k] * cptr->volume;
- }
- buffer[i] = l / 256;
- }
- }
-
- void
- worknote(note * nptr, channel * cptr)
- {
- uint sample, period, effect;
-
- sample = (nptr->sampperiod & 0xF0) | (nptr->sampeffect >> 4);
- period = ((nptr->sampperiod & 0xF) << 8) | nptr->period;
- effect = ((nptr->sampeffect & 0xF) << 8) | nptr->effect;
- if (period != 0) {
- if (sample != 0) cptr->sampnum = --sample;
- cptr->sampdata = sampledata[cptr->sampnum];
- cptr->length = song.samples[cptr->sampnum].length;
- cptr->reppnt = song.samples[cptr->sampnum].reppnt;
- cptr->replen = song.samples[cptr->sampnum].replen;
- cptr->volume = song.samples[cptr->sampnum].volume;
- cptr->period = period;
- cptr->ticks = 0;
- }
- switch (effect >> 8) {
- case 0xF: patternticksaim=(long)(effect&0xFF)*playrate/51;break;
- case 0xD: patternpos = (effect & 0xFF) * 4; tablepos++; break;
- case 0xC: cptr->volume = (effect & 0xFF); break;
- case 0xB: tablepos = (effect & 0xFF); break;
- case 0x9: cptr->sampdata += (effect & 0xFF) * 256; break;
- }
- }
-